//! Mock 系统日志 Appender 模块
//!
//! 提供用于测试的 Mock 系统日志实现，将日志存储到内存中供验证。
//!
//! ## 启用方式
//!
//! - `#[cfg(test)]` - 单元测试中自动可用
//! - `#[cfg(feature = "mock-syslog")]` - CI 环境通过 feature flag 启用
//!
//! ## 示例
//!
//! ```rust,ignore
//! use log4r::appender::syslog::mock::{
//!     MockSyslogAppender, get_mock_syslog_events, clear_mock_syslog_events
//! };
//! use log4r::{LogEvent, Level};
//!
//! // 清空之前的日志（测试隔离）
//! clear_mock_syslog_events();
//!
//! // 使用 Mock Appender
//! let appender = MockSyslogAppender::new("test_app");
//! let event = LogEvent::new(Level::Fatal, "test", "测试消息");
//! appender.write_syslog(&event).unwrap();
//!
//! // 验证捕获的日志
//! let events = get_mock_syslog_events();
//! assert_eq!(events.len(), 1);
//! assert_eq!(events[0].message, "测试消息");
//! ```

use std::sync::{Arc, LazyLock, Mutex};

use crate::error::Log4rError;
use crate::event::LogEvent;

use super::SyslogAppender;

/// 全局 Mock 日志存储
///
/// 使用 `LazyLock` 实现线程安全的延迟初始化。
/// 所有 `MockSyslogAppender` 实例共享此存储。
static MOCK_SYSLOG_EVENTS: LazyLock<Arc<Mutex<Vec<LogEvent>>>> =
    LazyLock::new(|| Arc::new(Mutex::new(Vec::new())));

/// Mock 系统日志 Appender
///
/// 用于测试环境，将日志存储到内存中供验证。
/// 通过 `mock-syslog` feature flag 或 `#[cfg(test)]` 启用。
///
/// ## 线程安全
///
/// `MockSyslogAppender` 实现 `Send + Sync`，可在多线程环境中安全使用。
///
/// ## 示例
///
/// ```rust,ignore
/// use log4r::appender::syslog::mock::MockSyslogAppender;
/// use log4r::appender::syslog::SyslogAppender;
/// use log4r::{LogEvent, Level};
///
/// let appender = MockSyslogAppender::new("my_app");
/// let event = LogEvent::new(Level::Fatal, "test", "错误消息");
/// appender.write_syslog(&event).unwrap();
/// ```
#[derive(Debug)]
pub struct MockSyslogAppender {
    /// 应用名称
    app_name: String,
}

impl MockSyslogAppender {
    /// 创建新的 Mock Appender
    ///
    /// # Arguments
    ///
    /// * `app_name` - 应用名称，用于标识日志来源
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use log4r::appender::syslog::mock::MockSyslogAppender;
    ///
    /// let appender = MockSyslogAppender::new("my_app");
    /// ```
    pub fn new(app_name: &str) -> Self {
        Self {
            app_name: app_name.to_string(),
        }
    }

    /// 获取应用名称
    ///
    /// # Returns
    ///
    /// 返回创建时指定的应用名称
    pub fn app_name(&self) -> &str {
        &self.app_name
    }
}

impl SyslogAppender for MockSyslogAppender {
    fn write_syslog(&self, event: &LogEvent) -> Result<(), Log4rError> {
        let mut events = MOCK_SYSLOG_EVENTS
            .lock()
            .map_err(|e| Log4rError::AppenderError {
                name: "MockSyslogAppender".to_string(),
                cause: format!("锁获取失败: {}", e),
            })?;
        events.push(event.clone());
        Ok(())
    }

    fn name(&self) -> &'static str {
        "MockSyslogAppender"
    }
}

/// 获取 Mock 捕获的系统日志事件
///
/// 返回所有通过 `MockSyslogAppender` 写入的日志事件副本。
/// 用于测试验证 FATAL 双写机制。
///
/// # Returns
///
/// 返回捕获的日志事件列表（克隆）
///
/// # Examples
///
/// ```rust,ignore
/// use log4r::appender::syslog::mock::{get_mock_syslog_events, clear_mock_syslog_events};
///
/// clear_mock_syslog_events();
/// // ... 执行一些日志操作 ...
/// let events = get_mock_syslog_events();
/// assert!(!events.is_empty());
/// ```
pub fn get_mock_syslog_events() -> Vec<LogEvent> {
    MOCK_SYSLOG_EVENTS
        .lock()
        .map(|events| events.clone())
        .unwrap_or_default()
}

/// 清空 Mock 系统日志事件
///
/// 用于测试隔离，在每个测试开始前清空之前的日志。
///
/// # Examples
///
/// ```rust,ignore
/// use log4r::appender::syslog::mock::clear_mock_syslog_events;
///
/// // 测试开始前清空
/// clear_mock_syslog_events();
/// ```
pub fn clear_mock_syslog_events() {
    if let Ok(mut events) = MOCK_SYSLOG_EVENTS.lock() {
        events.clear();
    }
}

// 编译时断言：验证 MockSyslogAppender 实现 Send + Sync
const _: () = {
    const fn assert_send_sync<T: Send + Sync>() {}
    assert_send_sync::<MockSyslogAppender>();
};

#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
    use super::*;
    use crate::level::Level;
    use serial_test::serial;

    // UT-8.6-001: MockSyslogAppender 实现 SyslogAppender trait (AC: 8.6.1)
    #[test]
    #[serial]
    fn test_mock_syslog_appender_implements_trait() {
        // GIVEN: MockSyslogAppender 实例
        let appender = MockSyslogAppender::new("test_app");

        // THEN: 应实现 SyslogAppender trait
        assert_eq!(appender.name(), "MockSyslogAppender");
        assert_eq!(appender.app_name(), "test_app");
    }

    // UT-8.6-002: MockSyslogAppender 正确存储日志事件 (AC: 8.6.2)
    #[test]
    #[serial]
    fn test_mock_syslog_appender_stores_events() {
        // GIVEN: 清空之前的日志
        clear_mock_syslog_events();
        let appender = MockSyslogAppender::new("test_app");
        let event = LogEvent::new(Level::Fatal, "test_target", "测试消息");

        // WHEN: 写入日志
        let result = appender.write_syslog(&event);

        // THEN: 写入成功，事件被存储
        assert!(result.is_ok());
        let events = get_mock_syslog_events();
        assert_eq!(events.len(), 1);
        assert_eq!(events[0].message, "测试消息");
        assert_eq!(events[0].target, "test_target");
        assert_eq!(events[0].level, Level::Fatal);
    }

    // UT-8.6-003: get_mock_syslog_events() 返回正确的日志列表 (AC: 8.6.5)
    #[test]
    #[serial]
    fn test_get_mock_syslog_events_returns_correct_list() {
        // GIVEN: 清空并写入多条日志
        clear_mock_syslog_events();
        let appender = MockSyslogAppender::new("test_app");

        let event1 = LogEvent::new(Level::Fatal, "target1", "消息1");
        let event2 = LogEvent::new(Level::Fatal, "target2", "消息2");
        let event3 = LogEvent::new(Level::Fatal, "target3", "消息3");

        appender.write_syslog(&event1).unwrap();
        appender.write_syslog(&event2).unwrap();
        appender.write_syslog(&event3).unwrap();

        // WHEN: 获取日志列表
        let events = get_mock_syslog_events();

        // THEN: 应返回所有日志，顺序正确
        assert_eq!(events.len(), 3);
        assert_eq!(events[0].message, "消息1");
        assert_eq!(events[1].message, "消息2");
        assert_eq!(events[2].message, "消息3");
    }

    // UT-8.6-004: clear_mock_syslog_events() 清空日志 (AC: 8.6.6)
    #[test]
    #[serial]
    fn test_clear_mock_syslog_events_clears_all() {
        // GIVEN: 写入一些日志
        clear_mock_syslog_events();
        let appender = MockSyslogAppender::new("test_app");
        let event = LogEvent::new(Level::Fatal, "test", "消息");
        appender.write_syslog(&event).unwrap();
        assert!(!get_mock_syslog_events().is_empty());

        // WHEN: 清空日志
        clear_mock_syslog_events();

        // THEN: 日志列表应为空
        assert!(get_mock_syslog_events().is_empty());
    }

    // UT-8.6-006: MockSyslogAppender 是 Send + Sync (AC: 8.6.1)
    #[test]
    fn test_mock_syslog_appender_is_send_sync() {
        // GIVEN/WHEN: 编译时断言函数
        fn assert_send<T: Send>() {}
        fn assert_sync<T: Sync>() {}

        // THEN: MockSyslogAppender 应实现 Send + Sync
        assert_send::<MockSyslogAppender>();
        assert_sync::<MockSyslogAppender>();
    }

    // UT-8.6-007: 多线程并发写入 Mock 不会 panic (AC: 8.6.2)
    #[test]
    #[serial]
    fn test_mock_syslog_concurrent_writes() {
        use std::sync::atomic::{AtomicUsize, Ordering};
        use std::sync::Arc;
        use std::thread;

        // GIVEN: 清空日志（确保隔离）
        clear_mock_syslog_events();
        let initial_count = get_mock_syslog_events().len();

        // 使用原子计数器跟踪成功写入数
        let success_count = Arc::new(AtomicUsize::new(0));

        // WHEN: 多线程并发写入
        let handles: Vec<_> = (0..10)
            .map(|i| {
                let counter = Arc::clone(&success_count);
                thread::spawn(move || {
                    let appender = MockSyslogAppender::new("concurrent_test");
                    let event = LogEvent::new(Level::Fatal, "thread", format!("消息 {}", i));
                    if appender.write_syslog(&event).is_ok() {
                        counter.fetch_add(1, Ordering::SeqCst);
                    }
                })
            })
            .collect();

        // 等待所有线程完成
        for handle in handles {
            handle.join().unwrap();
        }

        // THEN: 所有写入应成功，无 panic
        let final_count = get_mock_syslog_events().len();
        let written = final_count - initial_count;
        assert_eq!(
            success_count.load(Ordering::SeqCst),
            10,
            "应有 10 次成功写入"
        );
        assert!(written >= 10, "应至少写入 10 条日志，实际: {}", written);
    }

    // 测试空应用名称
    #[test]
    #[serial]
    fn test_mock_syslog_empty_app_name() {
        // GIVEN: 空应用名称
        let appender = MockSyslogAppender::new("");

        // THEN: 应正常创建
        assert_eq!(appender.app_name(), "");
    }

    // 测试 Unicode 应用名称
    #[test]
    #[serial]
    fn test_mock_syslog_unicode_app_name() {
        // GIVEN: Unicode 应用名称
        let appender = MockSyslogAppender::new("日志应用🚀");

        // THEN: 应正确保存
        assert_eq!(appender.app_name(), "日志应用🚀");
    }
}
